package org.belkodevelop.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.belkodevelop.geocoding.domen.GeoStatus;
import org.belkodevelop.geocoding.exception.GeoCodingConnectionException;
import org.belkodevelop.geocoding.exception.GeoCodingJSONParseException;
import org.belkodevelop.geocoding.exception.GeoCodingUnsupportedEncodingException;
import org.belkodevelop.geocoding.service.GeoCodingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/api/geocoding/")
public class GeoCodingController {
    
    private static final int TRY_CONNECT = 10;
    
    private final Log log = LogFactory.getLog(getClass()); 
    
    @Autowired
    private GeoCodingService geoCodingService;
    
    private Map<String, Object> createResultMap(List result, GeoStatus geoStatus) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("result", result);
        resultMap.put("status", geoStatus.toString());
        return resultMap;
    }
    
    @RequestMapping(method = RequestMethod.GET, value = "/json",  headers="Accept=*/*")
    @ResponseBody
    public Map<String, Object> execute(@RequestParam("address") String address, 
                        @RequestParam(value="sensor", required=false, defaultValue="true") String sensor,
                        @RequestParam(value="region", required=false, defaultValue="UA") String region,
                        @RequestParam(value="language", required=false, defaultValue="ru") String language) {
        log.debug(String.format("address=%s, sensor=%s, region=%s, language=%s", 
                address, sensor, region, language));
        int tryy = 0;
        do {
            try {
                return geoCodingService.sendRequest(address.trim(), Boolean.parseBoolean(sensor), 
                        region.trim(), language.trim());
            } catch (GeoCodingUnsupportedEncodingException ex) {

                return createResultMap(new ArrayList(), GeoStatus.INVALID_REQUEST);

            } catch (GeoCodingConnectionException ex) {
                log.warn("Connection error", ex);
                try {
                    Thread.sleep(100);
                    tryy++;
                    if (tryy == TRY_CONNECT) {
                        return createResultMap(new ArrayList(), GeoStatus.CONNECTION_ERROR);
                    }
                } catch (InterruptedException ex1) {
                    tryy = TRY_CONNECT;
                }

            } catch (GeoCodingJSONParseException ex) {
                log.error("Json parse error", ex);
                return createResultMap(new ArrayList(), GeoStatus.INVALID_RESPONCE);

            }
        } while(true);
    }
}
